1 /*
2 * Copyright (C) 2011 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.google.common.collect;
18
19 import com.google.common.annotations.GwtCompatible;
20
21 import java.util.Iterator;
22 import java.util.Map;
23 import java.util.Set;
24
25 /**
26 * Workaround for
27 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6312706">
28 * EnumMap bug</a>. If you want to pass an {@code EnumMap}, with the
29 * intention of using its {@code entrySet()} method, you should
30 * wrap the {@code EnumMap} in this class instead.
31 *
32 * <p>This class is not thread-safe even if the underlying map is.
33 *
34 * @author Dimitris Andreou
35 */
36 @GwtCompatible
37 final class WellBehavedMap<K, V> extends ForwardingMap<K, V> {
38 private final Map<K, V> delegate;
39 private Set<Entry<K, V>> entrySet;
40
41 private WellBehavedMap(Map<K, V> delegate) {
42 this.delegate = delegate;
43 }
44
45 /**
46 * Wraps the given map into a {@code WellBehavedEntriesMap}, which
47 * intercepts its {@code entrySet()} method by taking the
48 * {@code Set<K> keySet()} and transforming it to
49 * {@code Set<Entry<K, V>>}. All other invocations are delegated as-is.
50 */
51 static <K, V> WellBehavedMap<K, V> wrap(Map<K, V> delegate) {
52 return new WellBehavedMap<K, V>(delegate);
53 }
54
55 @Override protected Map<K, V> delegate() {
56 return delegate;
57 }
58
59 @Override public Set<Entry<K, V>> entrySet() {
60 Set<Entry<K, V>> es = entrySet;
61 if (es != null) {
62 return es;
63 }
64 return entrySet = new EntrySet();
65 }
66
67 private final class EntrySet extends Maps.EntrySet<K, V> {
68 @Override
69 Map<K, V> map() {
70 return WellBehavedMap.this;
71 }
72
73 @Override
74 public Iterator<Entry<K, V>> iterator() {
75 return new TransformedIterator<K, Entry<K, V>>(keySet().iterator()) {
76 @Override
77 Entry<K, V> transform(final K key) {
78 return new AbstractMapEntry<K, V>() {
79 @Override
80 public K getKey() {
81 return key;
82 }
83
84 @Override
85 public V getValue() {
86 return get(key);
87 }
88
89 @Override
90 public V setValue(V value) {
91 return put(key, value);
92 }
93 };
94 }
95 };
96 }
97 }
98 }